///////////////////////////////////////////////////////////////////////////
//
// Spring Engine Source File.
// Copyright (C), Dengtao 2011-2021
// ----------------------------------------------------------------------
// File name:   SfMessageDispatcher.h
// Version:     v1.0.0
// Created:     2013/06/16 20:20 by dengtao
// Compilers:   Visual Studio 2008
// Description: 
// ----------------------------------------------------------------------
// History:
//
///////////////////////////////////////////////////////////////////////////

#ifndef _SfMessageDispatcher_H_
#define _SfMessageDispatcher_H_

#include "SfMessage.h"
#include "SfSharedSingleton.h"
#include "SfDelegate.h"
#include "SfMessageHandler.h"
#include <list>
#include <map>

namespace Sunflower
{
//////////////////////////////////////////////////////////////////////////
//Summary:
//	message dispatcher.
//////////////////////////////////////////////////////////////////////////
class MessageDispatcher : public SharedSingleton<MessageDispatcher>
{
public:
	typedef Delegate<MessageHandleResult (const Message&)> 
		MessageHandleDelegate;

public:
	//
	//Summary:
	//	constructor.
	MessageDispatcher() : m_LastUpdateTime(0) {}

	//
	//Summary:
	//	destructor.
	virtual ~MessageDispatcher(){}

	//
	//Summary:
	//	post a message without delay.
	virtual void PostMessage(unsigned int msgId, 
		const GameObjectGUID& senderId, 
		const GameObjectGUID& recieverId, 
		MessageArgument* arg);
	virtual void PostMessage(unsigned int msgId, 
		GameObject* sender, 
		GameObject* reciever, 
		MessageArgument* arg);

	//
	//Summary:
	//	post a message with delay.
	virtual void PostDelayedMessage(unsigned int msgId, 
		const GameObjectGUID& senderId, 
		const GameObjectGUID& recieverId, 
		MessageArgument* arg,
		float delayTime);
	virtual void PostDelayedMessage(unsigned int msgId, 
		GameObject* sender, 
		GameObject* reciever, 
		MessageArgument* arg,
		float delayTime);

	//
	//Summary:
	//	Broadcast message.
	virtual void BroadcastMessage(unsigned int msgId, 
		const GameObjectGUID& senderId,
		MessageArgument* arg);
	virtual void BroadcastMessage(unsigned int msgId, 
		GameObject* sender,
		MessageArgument* arg);

	//
	//Summary:
	//	Broadcast message with delay
	virtual void BroadcastDelayedMessage(unsigned int msgId, 
		const GameObjectGUID& senderId,
		MessageArgument* arg,
		float delayTime);
	virtual void BroadcastDelayedMessage(unsigned int msgId, 
		GameObject* sender,
		MessageArgument* arg,
		float delayTime);

	//
	//Summary:
	//	Update with elapsed time.
	virtual void UpdateTime(float deltaTime);

	//
	//Summary:
	//	Update all delayed message.
	void UpdateAllDelayedMessages();

	//
	//Summary:
	//	reset.
	virtual void Reset();

	//
	//Summary:
	//	set unhandled message filter.
	void SetUnhandledMessageFilter(MessageHandleDelegate& mhd);

protected:
	//
	//Summary:
	//	Broadcast message to objects.
	void BroadcastMessage(const Message& message);

protected:
	MessageDispatcher(const MessageDispatcher&);
	MessageDispatcher& operator =(const MessageDispatcher&);

protected:
	struct DelayedMessageDispatchInfo
	{
		float DelayTime;
		bool Broadcast;
		Message message;
	};

	typedef std::list<DelayedMessageDispatchInfo> MessageQueue;
	typedef MessageQueue::iterator MessageQueueIterator;
	typedef MessageQueue::const_iterator MessageQueueConstIterator;

//
protected:
	// delayed message queue
	MessageQueue m_MessageQueue;

	// last update time.
	float m_LastUpdateTime;

	// unhandle message filter.
	MessageHandleDelegate m_UnhandledMessageFilter;
};

}

#endif
